#include <algorithm>
#include <bitset>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <istream>
#include <queue>
#include <vector>
// 引入这个头文件以使用 abs
#include <cmath> 

using ll = int; // 距离不会爆int，用int更快一点

const ll maxn=5e4+5,maxk=51,inf=1e9+7;
ll n,k,b[maxn];
std::vector<std::vector<int>> edg;
std::vector<std::vector<int>> classp;
ll vis[maxn];

struct P{
    ll now,step;
    inline bool operator<(const P&o)const{
        return step>o.step;
    }
};

int main(){
    std::iostream::sync_with_stdio(false);
    std::cin.tie(nullptr);

    std::cin>>n>>k;
    edg.resize(k+1);
    classp.resize(k+1);
    for(ll i=1;i<=n;i++){
        std::cin>>b[i];
        classp[b[i]].emplace_back(i);
        vis[i]=inf;
    }
    // 注意：classp 中的下标天然就是有序的（从小到大），所以不需要额外排序

    for(ll i=1;i<=k;i++){
        for(ll j=1;j<=k;j++){
            char tmp;
            std::cin>>tmp;
            if(tmp=='1'){
                edg[i].emplace_back(j);
            }
        }
    }

    std::priority_queue<P> pq;
    pq.emplace(1,0);
    // vis[1] = 0; // 严谨的Dijkstra最好在这里初始化，不过你的逻辑在下面判断也可以

    while(pq.size()){
        auto[now,step]=pq.top();
        pq.pop();
        
        // 这里的逻辑稍微调整一下，符合标准Dijkstra
        if(vis[now]!=inf) continue; 
        vis[now]=step; 

        if(now==n){
            std::cout<<step<<"\n";
            return 0;
        }

        // --- 修改开始 ---
        for(ll target_breed : edg[b[now]]){
            // 获取目标品种的所有位置列表
            const auto& vec = classp[target_breed];
            if(vec.empty()) continue;

            // 1. 找右边最近的一个 (第一个 > now 的位置)
            auto it = std::upper_bound(vec.begin(), vec.end(), now);
            if(it != vec.end()){
                ll p = *it;
                ll nstep = step + std::abs(p - now);
                // 只有当新路径更短，且该点未被“关闭”(未vis)时才入队
                // 注意：你之前的逻辑里 vis[p] 初始化是 inf，所以用 nstep < vis[p] 没问题
                // 但要注意 vis 在你的代码里既做“已访问标记”又存“最短路”。
                // 更安全的写法是只判断是否更优，因为如果 vis[p] 已经是更小的值，这里就不会进
                if(vis[p] == inf) { 
                     pq.emplace(p, nstep);
                }
            }

            // 2. 找左边最近的一个 (第一个 < now 的位置)
            // lower_bound 是 >= now，所以它的前一个就是 < now
            auto it_l = std::lower_bound(vec.begin(), vec.end(), now);
            if(it_l != vec.begin()){
                it_l--; // 往前移一位
                ll p = *it_l;
                ll nstep = step + std::abs(p - now);
                if(vis[p] == inf) {
                     pq.emplace(p, nstep);
                }
            }
        }
        // --- 修改结束 ---
    }
    std::cout<<"-1\n";
}